﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Web.Mvc;
using EzDesk.Apps.Model.ProjectModule;
using EzDesk.Clients.DesktopWeb.ViewModels;
using EzDesk.Utility.Extensions;
using EzDesk.Utility.ServiceStatusInfo;
using EzDesk.Utility.Web.Controllers;
using EzDesk.Utility.Web.Extensions;
using EzDesk.Utility.Web.ServiceReference;
using System.Linq;

namespace EzDesk.Clients.DesktopWeb.Controllers
{
    [Authorize]
    public partial class ProjectController : EzDeskAppController
    {


        #region [ Page Methods ]
        [HttpGet]
        public ActionResult DailyWork(long? time)
        {
            var isDisplayUnfinishedWorkitems = true;
            var isFuture = false;
            var date = getDateByDefault(time);

            if (date < DateTime.Now.Date)
                isDisplayUnfinishedWorkitems = false;
            if (date > DateTime.Now.Date)
                isFuture = true;

            dynamic model = new ExpandoObject();
            model.IsFuture = isFuture;

            if (isFuture == false)
            {
                var timeEopch = date.ToEpoch();
                var dailyWork = ProjectService.GetDailyWork(CurrentUserId, date).Result;

                model.DailyWork = dailyWork.DailyWork;
                model.IsDisplayUnfinishedWorkitems = isDisplayUnfinishedWorkitems;
                model.Time = timeEopch;
            }

            return View(model);
        }


        [HttpGet]
        public ActionResult DailyWorkList(long? time, Guid? userId)
        {
            var date = getDateByDefault(time);
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());

            dynamic model = new ExpandoObject();
            model.CurrentUser = currentUser;
            model.CurrentTime = date.Date;

            return View(model);
        }
        [HttpGet]
        public ActionResult DailyWorkListPerMonth(long? time)
        {
            var date = getDateByDefault(time);
            var startDate = date.AddDays(-date.Day);
            var endDate = startDate.AddMonths(1) < DateTime.Now ? startDate.AddMonths(1) : DateTime.Now;
            var dailyWorks = ProjectService.GetDailyWorks(CurrentUserId, startDate, endDate).Result;

            var viewModel = new List<dynamic>();
            var dailyWorkList = new List<dynamic>();
            var infoForCalendar = new List<dynamic>();

            var workitemsInMonth = ProjectService.GetWorkitems(CurrentUserId, null, null, null, null, true, null, null, startDate, endDate, null).Result;
            foreach (var workitem in workitemsInMonth)
            {
                if (workitem.Project != null)
                {
                    workitem.Project.Workitem = null;
                }
                if (workitem.Task != null)
                {
                    workitem.Task.Workitem = null;
                    if (workitem.Project != null) workitem.Project.Task = null;
                }
            }
            for (var day = startDate.Date; day <= endDate.Date; day = day.AddDays(1).Date)
            {
                if (day > DateTime.Now.Date) continue;
                //todo: 获取每天完成的任务列表
                var workitemPerDay = workitemsInMonth.Where(workitem => workitem.FinishOn.Value.Date == day.Date);
                var totalPoints = workitemPerDay.Aggregate(0, (current, workitem) => current + workitem.Points);
                var dailyWork = dailyWorks.FirstOrDefault(p => p.Day == day);
                var title = " ";

                if (workitemPerDay.Count() > 0)
                {
                    title = "完成 " + workitemPerDay.Count() + " " + "项任务";
                }
                infoForCalendar.Add(new
                {
                    Date = day.Date,
                    Title = title,
                });

                dailyWorkList.Add(new
                {
                    theDay = day.Date,
                    workitemList = workitemPerDay.OrderByDescending(w => w.FinishOn).ToList(),
                    totalPoints = totalPoints,
                    dailyWork = dailyWork.DailyWork,
                });
            }

            viewModel.Add(infoForCalendar);
            viewModel.Add(dailyWorkList);

            return Json(viewModel, JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public ActionResult WorkitemList()
        {
            dynamic model = new ExpandoObject();
            return View(model);
        }

        [HttpGet]
        public ActionResult AddWorkitem(Guid? userId)
        {
            return Redirect("/project/workitemList#create");
        }

        public ActionResult Workitem(Guid id)
        {
            var statusInfo = ProjectService.GetWorkitem(id);


            if (statusInfo.Status == ServiceStatus.Success)
            {
                dynamic model = new ExpandoObject();

                statusInfo.Result.CreatorName = EzApiClient.GetSimpleUserById(statusInfo.Result.CreatorId).Name;
                statusInfo.Result.OwnerName = statusInfo.Result.OwnerId.HasValue
                                                  ? EzApiClient.GetSimpleUserById(statusInfo.Result.OwnerId.Value).Name
                                                  : " - ";

                model.Workitem = statusInfo.Result;

                if (model.Workitem.Project != null)
                {
                    model.Workitem.Project.Workitem = null;
                }

                if (model.Workitem.IsFinished)
                {
                    return View("Workitem_Finished", model);
                }

                var isMine = CurrentUserId == statusInfo.Result.OwnerId ? true : false;
                model.IsMine = isMine;

                return View(model);
            }
            // todo: 定义通用的出错页面
            throw new Exception(statusInfo.Info);
        }


        [HttpGet]
        public ActionResult ConfirmWorkitem(Guid id)
        {
            ProjectService.ConfirmWorkItem(id, CurrentUserId);
            return RedirectToAction("WorkitemList", new { workitemId = id, isFinished = false });
        }

        [HttpGet]
        public ActionResult Statistics()
        {
            return View();
        }

        [HttpGet]
        public JsonResult WorkitemStatistics(long startDate, long endDate)
        {
            var startDay = getDateByDefault(startDate);
            var endDay = getDateByDefault(endDate);

            var workitemStatisitcs = ProjectService.GetWorkitemStatistics("everyone", startDay, endDay).Result;

            return Json(workitemStatisitcs);
        }

       
        #endregion

        #region [ Ajax Methods ]

        #region [ Get Workitems Methods ]
        /// <summary>
        /// 自己当天完成的任务
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        [HttpGet]
        public JsonResult OwnDailyFinishedWorkitems(long? dateTime)
        {
            DateTime date = getDateByDefault(dateTime).Date;
            var workitemList = ProjectService
                .GetWorkitems(CurrentUserId, null, null, null, null, true, null, null, date, date.AddDays(1), null)
                .Result
                .OrderByDescending(workitem => workitem.FinishOn)
                .ToList();

            workitemList.ForEach(wi => wi.PopulateCreatorNameAndOwnerName());

            return Json(workitemList, JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public JsonResult GetWorkItemStatuses()
        {
            var statuses = Enum
                .GetValues(typeof(WorkitemStatus))
                .Cast<WorkitemStatus>()
                .Select(s => new { Name = Enum.GetName(typeof(WorkitemStatus), s), Id = (int)s });

            return Json(statuses, JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public JsonResult GetWorkItems(WorkitemStatus? status, Guid? projectId, Guid? taskId, bool? onlyMine = true, bool? onlyMyAssign = false, bool? isFinish = false)
        {
            Guid? ownUserId = null;
            Guid? assignUserId = null;

            if (onlyMine.HasValue && onlyMine.Value)
                ownUserId = CurrentUserId;

            if (onlyMyAssign.HasValue && onlyMyAssign.Value)
                assignUserId = CurrentUserId;

            var workitemList = ProjectService
                .GetWorkitems(ownUserId, assignUserId, projectId, taskId, status, isFinish, null, null, null, null, null)
                .Result
                .ToList();

            if (onlyMyAssign.HasValue && onlyMyAssign.Value)
                workitemList = workitemList.Where(workitem => workitem.OwnerId != workitem.CreatorId).ToList();

            workitemList.ForEach(wi => wi.PopulateCreatorNameAndOwnerName());

            //foreach (var workitem in workitemList)
            //{
            //    workitem.PopulateCreatorNameAndOwnerName();
            //    if (workitem.Project != null)
            //    {
            //        workitem.Project.Workitem = null;
            //    }
            //    if (workitem.Task != null)
            //    {
            //        workitem.Task.Workitem = null;
            //        if (workitem.Project != null) workitem.Project.Task = null;
            //    }
            //}


            //TODO: refactorying
            // 排序
            workitemList = workitemList
                .OrderByDescending(w => w.UpdateOn)
                .ToList();

            // 把过期的和需要确认的提到前面
            var sortedList = new List<Workitem>();
            var expiredIndex = 0;
            var confirmIndex = 0;
            foreach (var workitem in workitemList)
            {
                if (workitem.OwnerId == CurrentUserId && workitem.Status == WorkitemStatus.Expired)
                {
                    sortedList.Insert(expiredIndex, workitem);
                    expiredIndex++;
                    confirmIndex++;
                }
                else if (workitem.OwnerId == CurrentUserId && workitem.Status == WorkitemStatus.WaitingForConfirm)
                {
                    sortedList.Insert(confirmIndex, workitem);
                    confirmIndex++;
                }
                else
                {
                    sortedList.Add(workitem);
                }
            }
            workitemList = sortedList;

            return Json(workitemList, JsonRequestBehavior.AllowGet);
        }


        #endregion

        [HttpPost]
        public JsonResult DoTakeOwnershipWorkitem(Guid workitemId)
        {
            var workitem = ProjectService.GetWorkitem(workitemId).Result;
            workitem.OwnerId = CurrentUserId;
            var statusInfo = ProjectService.UpdateWorkitem(workitem, CurrentUserId);

            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Data = new { workitemId };
                statusInfo.Info = "你已经成为了任务 " + workitem.Title + "的负责人";
            }
            return Json(statusInfo);
        }


        [HttpPost]
        public JsonResult DoConfirmWorkItem(Guid workitemId)
        {
            var statusInfo = ProjectService.ConfirmWorkItem(workitemId, CurrentUserId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Data = new { workitemId };
                statusInfo.Info = "任务已确认";
            }
            return Json(statusInfo);
        }

        [HttpPost]
        public JsonResult DoFinishWorkitem(Guid workitemId, int? points)
        {
            var estimatePoint = points ?? 0;
            var statusInfo = ProjectService.FinishWorkitem(workitemId, CurrentUserId, estimatePoint);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                var workitem = ProjectService.GetWorkitem(workitemId).Result;
                statusInfo.Data = new { workitemId };
                statusInfo.Info = string.Format("任务 \"{0}\" 已完成", workitem.Title);
            }
            return Json(statusInfo);
        }

        [HttpPost]
        public JsonResult DoExtendWorkitem(Guid id, DateTime newPlanOn)
        {
            var statusInfo = ProjectService.PostponeWorkitem(id, newPlanOn);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "任务延期完成。";
            }
            return Json(statusInfo);
        }

        [HttpPost]
        public JsonResult DoAddWorkItem(
            string title,  // 任务内容
            Guid? ownerId,
            string description,  // 任务备注（详细描述）
            int? points,  // 预估时间数
            DateTime? planOn,   //预计结束时间 
            Guid? projectId,      //关联项目
            Guid? taskId,
            bool? isTrace = false
            )
        {
            ////todo: 对参数进行判错
            //if (!ownerId.HasValue)
            //{
            //    ownerId = CurrentUserId;
            //}

            var workitem = new Workitem
                               {
                                   OwnerId = ownerId,
                                   CreatorId = CurrentUserId,
                                   Title = title,
                                   Points = points ?? 0,
                                   PlanOn = planOn.HasValue ? planOn : null,
                                   Description = description,
                                   ProjectId = projectId,
                                   IsTrace = isTrace.Value,
                                   TaskId = taskId,
                               };
            var statusInfo = ProjectService.AddWorkitem(workitem);

            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = string.Format("添加任务“{0}”完成", title);
                statusInfo.Data = new
                                      {
                                          workitemId = statusInfo.Result
                                      };
            }
            return Json(statusInfo);
        }

        [HttpPost]
        public JsonResult DoAddFinishedWorkItem(
            string title,  // 任务内容
            string description,  // 任务备注（详细描述）
            int? points,  // 预估时间数
            Guid? projectId
            )
        {
            //todo: 对参数进行判错

            var workitem = new Workitem
                               {
                                   OwnerId = CurrentUserId,
                                   CreatorId = CurrentUserId,
                                   Title = title,
                                   Description = description,
                                   Points = points ?? 0,
                                   IsFinished = true,
                                   ProjectId = projectId,
                                   FinishOn = DateTime.Now,
                               };
            var statusInfo = ProjectService.AddFinishedWorkitem(workitem);

            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = string.Format("添加任务“{0}”完成", title);
                statusInfo.Data = new
                {
                    workitemId = statusInfo.Result
                };
            }

            return Json(statusInfo);
        }

        [HttpPost]
        public ActionResult DoUpdateWorkItem(
            Guid id,
            string title,  // 任务内容
            Guid? ownerId,
            string description,  // 任务备注（详细描述）
            int? points,  // 预估时间数
            DateTime? planOn,   //预计结束时间 
            Guid? projectId,      //关联项目
            Guid? taskId,
            bool? isTrace = false
            )
        {
            var newWorkitem = new Workitem()
                                  {
                                      Id = id,
                                      Title = title,
                                      OwnerId = ownerId,
                                      PlanOn = planOn,
                                      Points = points ?? 0,
                                      Description = description,
                                      ProjectId = projectId,
                                      TaskId = taskId,
                                      IsTrace = isTrace.Value
                                  };

            var statusInfo = ProjectService.UpdateWorkitem(newWorkitem, CurrentUserId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = string.Format("任务信息已经更新");
            }
            return Json(statusInfo);
        }


        [HttpPost]
        public ActionResult DoUpdateDailyWork(long? datetime, string dailyWorkContent)
        {
            var day = getDateByDefault(datetime);
            var statusInfo = ProjectService.UpdateDailyWorks(CurrentUserId, day.Date, dailyWorkContent);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = string.Format("工作日志已经更新");
            }
            return Json(statusInfo);
        }


        #endregion

        #region [ private method ]
        private DateTime getDateByDefault(long? time)
        {
            var date = DateTime.Now.Date;
            if (time.HasValue)
            {
                date = EpochDateTimeExtension.FromEpoch(time.Value);
            }
            return date;
        }
        #endregion


        #region [ Partial Actions ]
        public ActionResult _createProjectShortcut(bool hasCreateProjectPermission)
        {
            return hasCreateProjectPermission ? View() : null;
        }
        #endregion
    }

}
